﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Exceptionless;
using Gmmy.DomainExtension;
using Gmmy.Utility;
using Gmmy.Utility.Enums;
using Gmmy.Utility.Extensions;
using Microsoft.Extensions.Logging;
using Surging.Core.Caching;
using Surging.Core.CPlatform.Cache;
using Surging.Core.ProxyGenerator;

namespace Gmmy.ApplicationExtension
{
    public class ProxyBaseService: ProxyServiceBase
    {
        private ILogger<object> _logger;
        private ICacheProvider _cacheProvider;
        public ExceptionlessClient ExceptionlessClient;

        public ProxyBaseService(ILogger<object> logger = null)
        {
            _logger = logger;
            _cacheProvider = CacheContainer.GetService<ICacheProvider>("MemoryCache");
            ExceptionlessClient = new ExceptionlessClient(c =>
            {
                c.ApiKey = GlobalSetting.ExceptionlessKey;
                c.ServerUrl = GlobalSetting.ExceptionlessService;
            });
        }

        public async Task<CustomApiResult> Do<T>(T t, Func<CustomApiResult, Task> runMethod)
        {
            var result = new CustomApiResult();
            try
            {
                switch (GetHandingStatic(t))
                {
                    case 0:
                        AddHandingStatic(t);//写入执行中状态
                        await runMethod(result);
                        result.code = CustomApiResultCode.Succ;
                        AddHandingStatic(t);//写入执行完毕状态
                        break;
                    case 2:
                        result.code = CustomApiResultCode.HttpPortErr;
                        result.message = "操作已执行完毕!";
                        break;
                    case 1:
                        result.code = CustomApiResultCode.HttpPortErr;
                        result.message = "操作执行中!";
                        break;
                }
            }
            catch (CustomException ce)
            {
                AddHandingStatic(t, true);//清空状态
                result.code = ce.code;
                result.message = ce.message;
            }
            catch (Exception e)
            {
                AddHandingStatic(t, true);//清空状态
                result.code = CustomApiResultCode.HttpPortErr;
                result.message = "出错了,请稍后再试";
                ExceptionlessClient.SubmitException(e.InnerException ?? e);

            }
            return result;
        }
        public async Task<CustomApiResult> Do(Func<CustomApiResult, Task> runMethod)
        {
            var result = new CustomApiResult();
            try
            {
                await runMethod(result);
                result.code = CustomApiResultCode.Succ;
            }
            catch (CustomException ce)
            {
                result.code = ce.code;
                result.message = ce.message;
            }
            catch (Exception e)
            {
                result.code = CustomApiResultCode.HttpPortErr;
                result.message = "出错了,请稍后再试";
                ExceptionlessClient.SubmitException(e.InnerException ?? e);
            }
            return result;
        }

        //获取同一个请求的执行状态
        private int GetHandingStatic<T>(T t)
        {
            if (t != null)
            {
                var request = t.MapTo<BaseRequest, T>();
                if (string.IsNullOrEmpty(request.UniqueKey))
                {
                    return 0;
                }
                var questStatic = _cacheProvider.Get<int>(request.UniqueKey);
                return questStatic;
            }
            else
            {
                return 0;
            }
        }
        //变更同一个请求的执行状态以实现消息幂等
        private void AddHandingStatic<T>(T t, bool remove = false)
        {
            if (t != null)
            {
                var request = t.MapTo<BaseRequest, T>();
                if (!string.IsNullOrEmpty(request.UniqueKey))
                {
                    var key = request.UniqueKey;
                    var questStatic = _cacheProvider.Get<int?>(key);
                    if (remove)
                    {
                        _cacheProvider.Remove(key);
                    }
                    else
                    {
                        if (questStatic == null)
                        {
                            _cacheProvider.Add(key, 1);
                        }
                        else if (questStatic == 1)
                        {
                            _cacheProvider.Remove(key);
                            _cacheProvider.Add(key, 2);
                        }
                    }
                }
            }
        }
    }
}
